{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Mask R-CNN - Train on Shapes Dataset\n",
    "\n",
    "\n",
    "This notebook shows how to train Mask R-CNN on your own dataset. To keep things simple we use a synthetic dataset of shapes (squares, triangles, and circles) which enables fast training. You'd still need a GPU, though, because the network backbone is a Resnet101, which would be too slow to train on a CPU. On a GPU, you can start to get okay-ish results in a few minutes, and good results in less than an hour.\n",
    "\n",
    "The code of the *Shapes* dataset is included below. It generates images on the fly, so it doesn't require downloading any data. And it can generate images of any size, so we pick a small image size to train faster. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import sys\n",
    "import random\n",
    "import math\n",
    "import re\n",
    "import time\n",
    "import numpy as np\n",
    "import cv2\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from config import Config\n",
    "import utils\n",
    "import model as modellib\n",
    "import visualize\n",
    "from model import log\n",
    "\n",
    "%matplotlib inline \n",
    "\n",
    "# Root directory of the project\n",
    "ROOT_DIR = os.getcwd()\n",
    "\n",
    "# Directory to save logs and trained model\n",
    "MODEL_DIR = os.path.join(ROOT_DIR, \"logs\")\n",
    "\n",
    "# Local path to trained weights file\n",
    "COCO_MODEL_PATH = os.path.join(ROOT_DIR, \"mask_rcnn_coco.h5\")\n",
    "# Download COCO trained weights from Releases if needed\n",
    "if not os.path.exists(COCO_MODEL_PATH):\n",
    "    utils.download_trained_weights(COCO_MODEL_PATH)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Configurations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Configurations:\n",
      "BACKBONE_SHAPES                [[32 32]\n",
      " [16 16]\n",
      " [ 8  8]\n",
      " [ 4  4]\n",
      " [ 2  2]]\n",
      "BACKBONE_STRIDES               [4, 8, 16, 32, 64]\n",
      "BATCH_SIZE                     8\n",
      "BBOX_STD_DEV                   [0.1 0.1 0.2 0.2]\n",
      "DETECTION_MAX_INSTANCES        100\n",
      "DETECTION_MIN_CONFIDENCE       0.7\n",
      "DETECTION_NMS_THRESHOLD        0.3\n",
      "GPU_COUNT                      1\n",
      "IMAGES_PER_GPU                 8\n",
      "IMAGE_MAX_DIM                  128\n",
      "IMAGE_MIN_DIM                  128\n",
      "IMAGE_PADDING                  True\n",
      "IMAGE_SHAPE                    [128 128   3]\n",
      "LEARNING_MOMENTUM              0.9\n",
      "LEARNING_RATE                  0.001\n",
      "MASK_POOL_SIZE                 14\n",
      "MASK_SHAPE                     [28, 28]\n",
      "MAX_GT_INSTANCES               100\n",
      "MEAN_PIXEL                     [123.7 116.8 103.9]\n",
      "MINI_MASK_SHAPE                (56, 56)\n",
      "NAME                           shapes\n",
      "NUM_CLASSES                    4\n",
      "POOL_SIZE                      7\n",
      "POST_NMS_ROIS_INFERENCE        1000\n",
      "POST_NMS_ROIS_TRAINING         2000\n",
      "ROI_POSITIVE_RATIO             0.33\n",
      "RPN_ANCHOR_RATIOS              [0.5, 1, 2]\n",
      "RPN_ANCHOR_SCALES              (8, 16, 32, 64, 128)\n",
      "RPN_ANCHOR_STRIDE              1\n",
      "RPN_BBOX_STD_DEV               [0.1 0.1 0.2 0.2]\n",
      "RPN_NMS_THRESHOLD              0.7\n",
      "RPN_TRAIN_ANCHORS_PER_IMAGE    256\n",
      "STEPS_PER_EPOCH                100\n",
      "TRAIN_ROIS_PER_IMAGE           32\n",
      "USE_MINI_MASK                  True\n",
      "USE_RPN_ROIS                   True\n",
      "VALIDATION_STEPS               5\n",
      "WEIGHT_DECAY                   0.0001\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "class ShapesConfig(Config):\n",
    "    \"\"\"Configuration for training on the toy shapes dataset.\n",
    "    Derives from the base Config class and overrides values specific\n",
    "    to the toy shapes dataset.\n",
    "    \"\"\"\n",
    "    # Give the configuration a recognizable name\n",
    "    NAME = \"shapes\"\n",
    "\n",
    "    # Train on 1 GPU and 8 images per GPU. We can put multiple images on each\n",
    "    # GPU because the images are small. Batch size is 8 (GPUs * images/GPU).\n",
    "    GPU_COUNT = 1\n",
    "    IMAGES_PER_GPU = 8\n",
    "\n",
    "    # Number of classes (including background)\n",
    "    NUM_CLASSES = 1 + 3  # background + 3 shapes\n",
    "\n",
    "    # Use small images for faster training. Set the limits of the small side\n",
    "    # the large side, and that determines the image shape.\n",
    "    IMAGE_MIN_DIM = 128\n",
    "    IMAGE_MAX_DIM = 128\n",
    "\n",
    "    # Use smaller anchors because our image and objects are small\n",
    "    RPN_ANCHOR_SCALES = (8, 16, 32, 64, 128)  # anchor side in pixels\n",
    "\n",
    "    # Reduce training ROIs per image because the images are small and have\n",
    "    # few objects. Aim to allow ROI sampling to pick 33% positive ROIs.\n",
    "    TRAIN_ROIS_PER_IMAGE = 32\n",
    "\n",
    "    # Use a small epoch since the data is simple\n",
    "    STEPS_PER_EPOCH = 100\n",
    "\n",
    "    # use small validation steps since the epoch is small\n",
    "    VALIDATION_STEPS = 5\n",
    "    \n",
    "config = ShapesConfig()\n",
    "config.display()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Notebook Preferences"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_ax(rows=1, cols=1, size=8):\n",
    "    \"\"\"Return a Matplotlib Axes array to be used in\n",
    "    all visualizations in the notebook. Provide a\n",
    "    central point to control graph sizes.\n",
    "    \n",
    "    Change the default size attribute to control the size\n",
    "    of rendered images\n",
    "    \"\"\"\n",
    "    _, ax = plt.subplots(rows, cols, figsize=(size*cols, size*rows))\n",
    "    return ax"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Dataset\n",
    "\n",
    "Create a synthetic dataset\n",
    "\n",
    "Extend the Dataset class and add a method to load the shapes dataset, `load_shapes()`, and override the following methods:\n",
    "\n",
    "* load_image()\n",
    "* load_mask()\n",
    "* image_reference()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ShapesDataset(utils.Dataset):\n",
    "    \"\"\"Generates the shapes synthetic dataset. The dataset consists of simple\n",
    "    shapes (triangles, squares, circles) placed randomly on a blank surface.\n",
    "    The images are generated on the fly. No file access required.\n",
    "    \"\"\"\n",
    "\n",
    "    def load_shapes(self, count, height, width):\n",
    "        \"\"\"Generate the requested number of synthetic images.\n",
    "        count: number of images to generate.\n",
    "        height, width: the size of the generated images.\n",
    "        \"\"\"\n",
    "        # Add classes\n",
    "        self.add_class(\"shapes\", 1, \"square\")\n",
    "        self.add_class(\"shapes\", 2, \"circle\")\n",
    "        self.add_class(\"shapes\", 3, \"triangle\")\n",
    "\n",
    "        # Add images\n",
    "        # Generate random specifications of images (i.e. color and\n",
    "        # list of shapes sizes and locations). This is more compact than\n",
    "        # actual images. Images are generated on the fly in load_image().\n",
    "        for i in range(count):\n",
    "            bg_color, shapes = self.random_image(height, width)\n",
    "            self.add_image(\"shapes\", image_id=i, path=None,\n",
    "                           width=width, height=height,\n",
    "                           bg_color=bg_color, shapes=shapes)\n",
    "\n",
    "    def load_image(self, image_id):\n",
    "        \"\"\"Generate an image from the specs of the given image ID.\n",
    "        Typically this function loads the image from a file, but\n",
    "        in this case it generates the image on the fly from the\n",
    "        specs in image_info.\n",
    "        \"\"\"\n",
    "        info = self.image_info[image_id]\n",
    "        bg_color = np.array(info['bg_color']).reshape([1, 1, 3])\n",
    "        image = np.ones([info['height'], info['width'], 3], dtype=np.uint8)\n",
    "        image = image * bg_color.astype(np.uint8)\n",
    "        for shape, color, dims in info['shapes']:\n",
    "            image = self.draw_shape(image, shape, dims, color)\n",
    "        return image\n",
    "\n",
    "    def image_reference(self, image_id):\n",
    "        \"\"\"Return the shapes data of the image.\"\"\"\n",
    "        info = self.image_info[image_id]\n",
    "        if info[\"source\"] == \"shapes\":\n",
    "            return info[\"shapes\"]\n",
    "        else:\n",
    "            super(self.__class__).image_reference(self, image_id)\n",
    "\n",
    "    def load_mask(self, image_id):\n",
    "        \"\"\"Generate instance masks for shapes of the given image ID.\n",
    "        \"\"\"\n",
    "        info = self.image_info[image_id]\n",
    "        shapes = info['shapes']\n",
    "        count = len(shapes)\n",
    "        mask = np.zeros([info['height'], info['width'], count], dtype=np.uint8)\n",
    "        for i, (shape, _, dims) in enumerate(info['shapes']):\n",
    "            mask[:, :, i:i+1] = self.draw_shape(mask[:, :, i:i+1].copy(),\n",
    "                                                shape, dims, 1)\n",
    "        # Handle occlusions\n",
    "        occlusion = np.logical_not(mask[:, :, -1]).astype(np.uint8)\n",
    "        for i in range(count-2, -1, -1):\n",
    "            mask[:, :, i] = mask[:, :, i] * occlusion\n",
    "            occlusion = np.logical_and(occlusion, np.logical_not(mask[:, :, i]))\n",
    "        # Map class names to class IDs.\n",
    "        class_ids = np.array([self.class_names.index(s[0]) for s in shapes])\n",
    "        return mask, class_ids.astype(np.int32)\n",
    "\n",
    "    def draw_shape(self, image, shape, dims, color):\n",
    "        \"\"\"Draws a shape from the given specs.\"\"\"\n",
    "        # Get the center x, y and the size s\n",
    "        x, y, s = dims\n",
    "        if shape == 'square':\n",
    "            cv2.rectangle(image, (x-s, y-s), (x+s, y+s), color, -1)\n",
    "        elif shape == \"circle\":\n",
    "            cv2.circle(image, (x, y), s, color, -1)\n",
    "        elif shape == \"triangle\":\n",
    "            points = np.array([[(x, y-s),\n",
    "                                (x-s/math.sin(math.radians(60)), y+s),\n",
    "                                (x+s/math.sin(math.radians(60)), y+s),\n",
    "                                ]], dtype=np.int32)\n",
    "            cv2.fillPoly(image, points, color)\n",
    "        return image\n",
    "\n",
    "    def random_shape(self, height, width):\n",
    "        \"\"\"Generates specifications of a random shape that lies within\n",
    "        the given height and width boundaries.\n",
    "        Returns a tuple of three valus:\n",
    "        * The shape name (square, circle, ...)\n",
    "        * Shape color: a tuple of 3 values, RGB.\n",
    "        * Shape dimensions: A tuple of values that define the shape size\n",
    "                            and location. Differs per shape type.\n",
    "        \"\"\"\n",
    "        # Shape\n",
    "        shape = random.choice([\"square\", \"circle\", \"triangle\"])\n",
    "        # Color\n",
    "        color = tuple([random.randint(0, 255) for _ in range(3)])\n",
    "        # Center x, y\n",
    "        buffer = 20\n",
    "        y = random.randint(buffer, height - buffer - 1)\n",
    "        x = random.randint(buffer, width - buffer - 1)\n",
    "        # Size\n",
    "        s = random.randint(buffer, height//4)\n",
    "        return shape, color, (x, y, s)\n",
    "\n",
    "    def random_image(self, height, width):\n",
    "        \"\"\"Creates random specifications of an image with multiple shapes.\n",
    "        Returns the background color of the image and a list of shape\n",
    "        specifications that can be used to draw the image.\n",
    "        \"\"\"\n",
    "        # Pick random background color\n",
    "        bg_color = np.array([random.randint(0, 255) for _ in range(3)])\n",
    "        # Generate a few random shapes and record their\n",
    "        # bounding boxes\n",
    "        shapes = []\n",
    "        boxes = []\n",
    "        N = random.randint(1, 4)\n",
    "        for _ in range(N):\n",
    "            shape, color, dims = self.random_shape(height, width)\n",
    "            shapes.append((shape, color, dims))\n",
    "            x, y, s = dims\n",
    "            boxes.append([y-s, x-s, y+s, x+s])\n",
    "        # Apply non-max suppression wit 0.3 threshold to avoid\n",
    "        # shapes covering each other\n",
    "        keep_ixs = utils.non_max_suppression(np.array(boxes), np.arange(N), 0.3)\n",
    "        shapes = [s for i, s in enumerate(shapes) if i in keep_ixs]\n",
    "        return bg_color, shapes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Training dataset\n",
    "dataset_train = ShapesDataset()\n",
    "dataset_train.load_shapes(500, config.IMAGE_SHAPE[0], config.IMAGE_SHAPE[1])\n",
    "dataset_train.prepare()\n",
    "\n",
    "# Validation dataset\n",
    "dataset_val = ShapesDataset()\n",
    "dataset_val.load_shapes(50, config.IMAGE_SHAPE[0], config.IMAGE_SHAPE[1])\n",
    "dataset_val.prepare()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1008x360 with 5 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1008x360 with 5 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1008x360 with 5 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1008x360 with 5 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Load and display random samples\n",
    "image_ids = np.random.choice(dataset_train.image_ids, 4)\n",
    "for image_id in image_ids:\n",
    "    image = dataset_train.load_image(image_id)\n",
    "    mask, class_ids = dataset_train.load_mask(image_id)\n",
    "    visualize.display_top_masks(image, mask, class_ids, dataset_train.class_names)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ceate Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create model in training mode\n",
    "model = modellib.MaskRCNN(mode=\"training\", config=config,\n",
    "                          model_dir=MODEL_DIR)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "# Which weights to start with?\n",
    "init_with = \"coco\"  # imagenet, coco, or last\n",
    "\n",
    "if init_with == \"imagenet\":\n",
    "    model.load_weights(model.get_imagenet_weights(), by_name=True)\n",
    "elif init_with == \"coco\":\n",
    "    # Load weights trained on MS COCO, but skip layers that\n",
    "    # are different due to the different number of classes\n",
    "    # See README for instructions to download the COCO weights\n",
    "    model.load_weights(COCO_MODEL_PATH, by_name=True,\n",
    "                       exclude=[\"mrcnn_class_logits\", \"mrcnn_bbox_fc\", \n",
    "                                \"mrcnn_bbox\", \"mrcnn_mask\"])\n",
    "elif init_with == \"last\":\n",
    "    # Load the last model you trained and continue training\n",
    "    model.load_weights(model.find_last()[1], by_name=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Training\n",
    "\n",
    "Train in two stages:\n",
    "1. Only the heads. Here we're freezing all the backbone layers and training only the randomly initialized layers (i.e. the ones that we didn't use pre-trained weights from MS COCO). To train only the head layers, pass `layers='heads'` to the `train()` function.\n",
    "\n",
    "2. Fine-tune all layers. For this simple example it's not necessary, but we're including it to show the process. Simply pass `layers=\"all` to train all layers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Starting at epoch 0. LR=0.001\n",
      "\n",
      "Checkpoint Path: /home/lvshoulu/test-env3/src/github/Mask_RCNN/logs/shapes20180308T2211/mask_rcnn_shapes_{epoch:04d}.h5\n",
      "Selecting layers to train\n",
      "fpn_c5p5               (Conv2D)\n",
      "fpn_c4p4               (Conv2D)\n",
      "fpn_c3p3               (Conv2D)\n",
      "fpn_c2p2               (Conv2D)\n",
      "fpn_p5                 (Conv2D)\n",
      "fpn_p2                 (Conv2D)\n",
      "fpn_p3                 (Conv2D)\n",
      "fpn_p4                 (Conv2D)\n",
      "In model:  rpn_model\n",
      "    rpn_conv_shared        (Conv2D)\n",
      "    rpn_class_raw          (Conv2D)\n",
      "    rpn_bbox_pred          (Conv2D)\n",
      "mrcnn_mask_conv1       (TimeDistributed)\n",
      "mrcnn_mask_bn1         (TimeDistributed)\n",
      "mrcnn_mask_conv2       (TimeDistributed)\n",
      "mrcnn_mask_bn2         (TimeDistributed)\n",
      "mrcnn_class_conv1      (TimeDistributed)\n",
      "mrcnn_class_bn1        (TimeDistributed)\n",
      "mrcnn_mask_conv3       (TimeDistributed)\n",
      "mrcnn_mask_bn3         (TimeDistributed)\n",
      "mrcnn_class_conv2      (TimeDistributed)\n",
      "mrcnn_class_bn2        (TimeDistributed)\n",
      "mrcnn_mask_conv4       (TimeDistributed)\n",
      "mrcnn_mask_bn4         (TimeDistributed)\n",
      "mrcnn_bbox_fc          (TimeDistributed)\n",
      "mrcnn_mask_deconv      (TimeDistributed)\n",
      "mrcnn_class_logits     (TimeDistributed)\n",
      "mrcnn_mask             (TimeDistributed)\n",
      "WARNING:tensorflow:From /home/lvshoulu/test-env3/src/github/Mask_RCNN/model.py:2073: calling reduce_mean (from tensorflow.python.ops.math_ops) with keep_dims is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "keep_dims is deprecated, use keepdims instead\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/lvshoulu/test-env3/env2/lib/python3.4/site-packages/tensorflow/python/ops/gradients_impl.py:98: UserWarning: Converting sparse IndexedSlices to a dense Tensor of unknown shape. This may consume a large amount of memory.\n",
      "  \"Converting sparse IndexedSlices to a dense Tensor of unknown shape. \"\n",
      "/home/lvshoulu/test-env3/env2/lib/python3.4/site-packages/keras/engine/training.py:2087: UserWarning: Using a generator with `use_multiprocessing=True` and multiple workers may duplicate your data. Please consider using the`keras.utils.Sequence class.\n",
      "  UserWarning('Using a generator with `use_multiprocessing=True`'\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/1\n",
      "100/100 [==============================] - 1361s 14s/step - loss: 1.7211 - rpn_class_loss: 0.0302 - rpn_bbox_loss: 0.5756 - mrcnn_class_loss: 0.3285 - mrcnn_bbox_loss: 0.3885 - mrcnn_mask_loss: 0.3983 - val_loss: 0.7029 - val_rpn_class_loss: 0.0219 - val_rpn_bbox_loss: 0.3295 - val_mrcnn_class_loss: 0.0855 - val_mrcnn_bbox_loss: 0.1154 - val_mrcnn_mask_loss: 0.1506\n"
     ]
    }
   ],
   "source": [
    "# Train the head branches\n",
    "# Passing layers=\"heads\" freezes all layers except the head\n",
    "# layers. You can also pass a regular expression to select\n",
    "# which layers to train by name pattern.\n",
    "model.train(dataset_train, dataset_val, \n",
    "            learning_rate=config.LEARNING_RATE, \n",
    "            epochs=1, \n",
    "            layers='heads')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Starting at epoch 1. LR=0.0001\n",
      "\n",
      "Checkpoint Path: /home/lvshoulu/test-env3/src/github/Mask_RCNN/logs/shapes20180308T2211/mask_rcnn_shapes_{epoch:04d}.h5\n",
      "Selecting layers to train\n",
      "conv1                  (Conv2D)\n",
      "bn_conv1               (BatchNorm)\n",
      "res2a_branch2a         (Conv2D)\n",
      "bn2a_branch2a          (BatchNorm)\n",
      "res2a_branch2b         (Conv2D)\n",
      "bn2a_branch2b          (BatchNorm)\n",
      "res2a_branch2c         (Conv2D)\n",
      "res2a_branch1          (Conv2D)\n",
      "bn2a_branch2c          (BatchNorm)\n",
      "bn2a_branch1           (BatchNorm)\n",
      "res2b_branch2a         (Conv2D)\n",
      "bn2b_branch2a          (BatchNorm)\n",
      "res2b_branch2b         (Conv2D)\n",
      "bn2b_branch2b          (BatchNorm)\n",
      "res2b_branch2c         (Conv2D)\n",
      "bn2b_branch2c          (BatchNorm)\n",
      "res2c_branch2a         (Conv2D)\n",
      "bn2c_branch2a          (BatchNorm)\n",
      "res2c_branch2b         (Conv2D)\n",
      "bn2c_branch2b          (BatchNorm)\n",
      "res2c_branch2c         (Conv2D)\n",
      "bn2c_branch2c          (BatchNorm)\n",
      "res3a_branch2a         (Conv2D)\n",
      "bn3a_branch2a          (BatchNorm)\n",
      "res3a_branch2b         (Conv2D)\n",
      "bn3a_branch2b          (BatchNorm)\n",
      "res3a_branch2c         (Conv2D)\n",
      "res3a_branch1          (Conv2D)\n",
      "bn3a_branch2c          (BatchNorm)\n",
      "bn3a_branch1           (BatchNorm)\n",
      "res3b_branch2a         (Conv2D)\n",
      "bn3b_branch2a          (BatchNorm)\n",
      "res3b_branch2b         (Conv2D)\n",
      "bn3b_branch2b          (BatchNorm)\n",
      "res3b_branch2c         (Conv2D)\n",
      "bn3b_branch2c          (BatchNorm)\n",
      "res3c_branch2a         (Conv2D)\n",
      "bn3c_branch2a          (BatchNorm)\n",
      "res3c_branch2b         (Conv2D)\n",
      "bn3c_branch2b          (BatchNorm)\n",
      "res3c_branch2c         (Conv2D)\n",
      "bn3c_branch2c          (BatchNorm)\n",
      "res3d_branch2a         (Conv2D)\n",
      "bn3d_branch2a          (BatchNorm)\n",
      "res3d_branch2b         (Conv2D)\n",
      "bn3d_branch2b          (BatchNorm)\n",
      "res3d_branch2c         (Conv2D)\n",
      "bn3d_branch2c          (BatchNorm)\n",
      "res4a_branch2a         (Conv2D)\n",
      "bn4a_branch2a          (BatchNorm)\n",
      "res4a_branch2b         (Conv2D)\n",
      "bn4a_branch2b          (BatchNorm)\n",
      "res4a_branch2c         (Conv2D)\n",
      "res4a_branch1          (Conv2D)\n",
      "bn4a_branch2c          (BatchNorm)\n",
      "bn4a_branch1           (BatchNorm)\n",
      "res4b_branch2a         (Conv2D)\n",
      "bn4b_branch2a          (BatchNorm)\n",
      "res4b_branch2b         (Conv2D)\n",
      "bn4b_branch2b          (BatchNorm)\n",
      "res4b_branch2c         (Conv2D)\n",
      "bn4b_branch2c          (BatchNorm)\n",
      "res4c_branch2a         (Conv2D)\n",
      "bn4c_branch2a          (BatchNorm)\n",
      "res4c_branch2b         (Conv2D)\n",
      "bn4c_branch2b          (BatchNorm)\n",
      "res4c_branch2c         (Conv2D)\n",
      "bn4c_branch2c          (BatchNorm)\n",
      "res4d_branch2a         (Conv2D)\n",
      "bn4d_branch2a          (BatchNorm)\n",
      "res4d_branch2b         (Conv2D)\n",
      "bn4d_branch2b          (BatchNorm)\n",
      "res4d_branch2c         (Conv2D)\n",
      "bn4d_branch2c          (BatchNorm)\n",
      "res4e_branch2a         (Conv2D)\n",
      "bn4e_branch2a          (BatchNorm)\n",
      "res4e_branch2b         (Conv2D)\n",
      "bn4e_branch2b          (BatchNorm)\n",
      "res4e_branch2c         (Conv2D)\n",
      "bn4e_branch2c          (BatchNorm)\n",
      "res4f_branch2a         (Conv2D)\n",
      "bn4f_branch2a          (BatchNorm)\n",
      "res4f_branch2b         (Conv2D)\n",
      "bn4f_branch2b          (BatchNorm)\n",
      "res4f_branch2c         (Conv2D)\n",
      "bn4f_branch2c          (BatchNorm)\n",
      "res4g_branch2a         (Conv2D)\n",
      "bn4g_branch2a          (BatchNorm)\n",
      "res4g_branch2b         (Conv2D)\n",
      "bn4g_branch2b          (BatchNorm)\n",
      "res4g_branch2c         (Conv2D)\n",
      "bn4g_branch2c          (BatchNorm)\n",
      "res4h_branch2a         (Conv2D)\n",
      "bn4h_branch2a          (BatchNorm)\n",
      "res4h_branch2b         (Conv2D)\n",
      "bn4h_branch2b          (BatchNorm)\n",
      "res4h_branch2c         (Conv2D)\n",
      "bn4h_branch2c          (BatchNorm)\n",
      "res4i_branch2a         (Conv2D)\n",
      "bn4i_branch2a          (BatchNorm)\n",
      "res4i_branch2b         (Conv2D)\n",
      "bn4i_branch2b          (BatchNorm)\n",
      "res4i_branch2c         (Conv2D)\n",
      "bn4i_branch2c          (BatchNorm)\n",
      "res4j_branch2a         (Conv2D)\n",
      "bn4j_branch2a          (BatchNorm)\n",
      "res4j_branch2b         (Conv2D)\n",
      "bn4j_branch2b          (BatchNorm)\n",
      "res4j_branch2c         (Conv2D)\n",
      "bn4j_branch2c          (BatchNorm)\n",
      "res4k_branch2a         (Conv2D)\n",
      "bn4k_branch2a          (BatchNorm)\n",
      "res4k_branch2b         (Conv2D)\n",
      "bn4k_branch2b          (BatchNorm)\n",
      "res4k_branch2c         (Conv2D)\n",
      "bn4k_branch2c          (BatchNorm)\n",
      "res4l_branch2a         (Conv2D)\n",
      "bn4l_branch2a          (BatchNorm)\n",
      "res4l_branch2b         (Conv2D)\n",
      "bn4l_branch2b          (BatchNorm)\n",
      "res4l_branch2c         (Conv2D)\n",
      "bn4l_branch2c          (BatchNorm)\n",
      "res4m_branch2a         (Conv2D)\n",
      "bn4m_branch2a          (BatchNorm)\n",
      "res4m_branch2b         (Conv2D)\n",
      "bn4m_branch2b          (BatchNorm)\n",
      "res4m_branch2c         (Conv2D)\n",
      "bn4m_branch2c          (BatchNorm)\n",
      "res4n_branch2a         (Conv2D)\n",
      "bn4n_branch2a          (BatchNorm)\n",
      "res4n_branch2b         (Conv2D)\n",
      "bn4n_branch2b          (BatchNorm)\n",
      "res4n_branch2c         (Conv2D)\n",
      "bn4n_branch2c          (BatchNorm)\n",
      "res4o_branch2a         (Conv2D)\n",
      "bn4o_branch2a          (BatchNorm)\n",
      "res4o_branch2b         (Conv2D)\n",
      "bn4o_branch2b          (BatchNorm)\n",
      "res4o_branch2c         (Conv2D)\n",
      "bn4o_branch2c          (BatchNorm)\n",
      "res4p_branch2a         (Conv2D)\n",
      "bn4p_branch2a          (BatchNorm)\n",
      "res4p_branch2b         (Conv2D)\n",
      "bn4p_branch2b          (BatchNorm)\n",
      "res4p_branch2c         (Conv2D)\n",
      "bn4p_branch2c          (BatchNorm)\n",
      "res4q_branch2a         (Conv2D)\n",
      "bn4q_branch2a          (BatchNorm)\n",
      "res4q_branch2b         (Conv2D)\n",
      "bn4q_branch2b          (BatchNorm)\n",
      "res4q_branch2c         (Conv2D)\n",
      "bn4q_branch2c          (BatchNorm)\n",
      "res4r_branch2a         (Conv2D)\n",
      "bn4r_branch2a          (BatchNorm)\n",
      "res4r_branch2b         (Conv2D)\n",
      "bn4r_branch2b          (BatchNorm)\n",
      "res4r_branch2c         (Conv2D)\n",
      "bn4r_branch2c          (BatchNorm)\n",
      "res4s_branch2a         (Conv2D)\n",
      "bn4s_branch2a          (BatchNorm)\n",
      "res4s_branch2b         (Conv2D)\n",
      "bn4s_branch2b          (BatchNorm)\n",
      "res4s_branch2c         (Conv2D)\n",
      "bn4s_branch2c          (BatchNorm)\n",
      "res4t_branch2a         (Conv2D)\n",
      "bn4t_branch2a          (BatchNorm)\n",
      "res4t_branch2b         (Conv2D)\n",
      "bn4t_branch2b          (BatchNorm)\n",
      "res4t_branch2c         (Conv2D)\n",
      "bn4t_branch2c          (BatchNorm)\n",
      "res4u_branch2a         (Conv2D)\n",
      "bn4u_branch2a          (BatchNorm)\n",
      "res4u_branch2b         (Conv2D)\n",
      "bn4u_branch2b          (BatchNorm)\n",
      "res4u_branch2c         (Conv2D)\n",
      "bn4u_branch2c          (BatchNorm)\n",
      "res4v_branch2a         (Conv2D)\n",
      "bn4v_branch2a          (BatchNorm)\n",
      "res4v_branch2b         (Conv2D)\n",
      "bn4v_branch2b          (BatchNorm)\n",
      "res4v_branch2c         (Conv2D)\n",
      "bn4v_branch2c          (BatchNorm)\n",
      "res4w_branch2a         (Conv2D)\n",
      "bn4w_branch2a          (BatchNorm)\n",
      "res4w_branch2b         (Conv2D)\n",
      "bn4w_branch2b          (BatchNorm)\n",
      "res4w_branch2c         (Conv2D)\n",
      "bn4w_branch2c          (BatchNorm)\n",
      "res5a_branch2a         (Conv2D)\n",
      "bn5a_branch2a          (BatchNorm)\n",
      "res5a_branch2b         (Conv2D)\n",
      "bn5a_branch2b          (BatchNorm)\n",
      "res5a_branch2c         (Conv2D)\n",
      "res5a_branch1          (Conv2D)\n",
      "bn5a_branch2c          (BatchNorm)\n",
      "bn5a_branch1           (BatchNorm)\n",
      "res5b_branch2a         (Conv2D)\n",
      "bn5b_branch2a          (BatchNorm)\n",
      "res5b_branch2b         (Conv2D)\n",
      "bn5b_branch2b          (BatchNorm)\n",
      "res5b_branch2c         (Conv2D)\n",
      "bn5b_branch2c          (BatchNorm)\n",
      "res5c_branch2a         (Conv2D)\n",
      "bn5c_branch2a          (BatchNorm)\n",
      "res5c_branch2b         (Conv2D)\n",
      "bn5c_branch2b          (BatchNorm)\n",
      "res5c_branch2c         (Conv2D)\n",
      "bn5c_branch2c          (BatchNorm)\n",
      "fpn_c5p5               (Conv2D)\n",
      "fpn_c4p4               (Conv2D)\n",
      "fpn_c3p3               (Conv2D)\n",
      "fpn_c2p2               (Conv2D)\n",
      "fpn_p5                 (Conv2D)\n",
      "fpn_p2                 (Conv2D)\n",
      "fpn_p3                 (Conv2D)\n",
      "fpn_p4                 (Conv2D)\n",
      "In model:  rpn_model\n",
      "    rpn_conv_shared        (Conv2D)\n",
      "    rpn_class_raw          (Conv2D)\n",
      "    rpn_bbox_pred          (Conv2D)\n",
      "mrcnn_mask_conv1       (TimeDistributed)\n",
      "mrcnn_mask_bn1         (TimeDistributed)\n",
      "mrcnn_mask_conv2       (TimeDistributed)\n",
      "mrcnn_mask_bn2         (TimeDistributed)\n",
      "mrcnn_class_conv1      (TimeDistributed)\n",
      "mrcnn_class_bn1        (TimeDistributed)\n",
      "mrcnn_mask_conv3       (TimeDistributed)\n",
      "mrcnn_mask_bn3         (TimeDistributed)\n",
      "mrcnn_class_conv2      (TimeDistributed)\n",
      "mrcnn_class_bn2        (TimeDistributed)\n",
      "mrcnn_mask_conv4       (TimeDistributed)\n",
      "mrcnn_mask_bn4         (TimeDistributed)\n",
      "mrcnn_bbox_fc          (TimeDistributed)\n",
      "mrcnn_mask_deconv      (TimeDistributed)\n",
      "mrcnn_class_logits     (TimeDistributed)\n",
      "mrcnn_mask             (TimeDistributed)\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/lvshoulu/test-env3/env2/lib/python3.4/site-packages/tensorflow/python/ops/gradients_impl.py:98: UserWarning: Converting sparse IndexedSlices to a dense Tensor of unknown shape. This may consume a large amount of memory.\n",
      "  \"Converting sparse IndexedSlices to a dense Tensor of unknown shape. \"\n",
      "/home/lvshoulu/test-env3/env2/lib/python3.4/site-packages/keras/engine/training.py:2087: UserWarning: Using a generator with `use_multiprocessing=True` and multiple workers may duplicate your data. Please consider using the`keras.utils.Sequence class.\n",
      "  UserWarning('Using a generator with `use_multiprocessing=True`'\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 2/2\n",
      "100/100 [==============================] - 1612s 16s/step - loss: 0.9420 - rpn_class_loss: 0.0156 - rpn_bbox_loss: 0.4091 - mrcnn_class_loss: 0.1269 - mrcnn_bbox_loss: 0.1425 - mrcnn_mask_loss: 0.2478 - val_loss: 0.8718 - val_rpn_class_loss: 0.0160 - val_rpn_bbox_loss: 0.4156 - val_mrcnn_class_loss: 0.1159 - val_mrcnn_bbox_loss: 0.1233 - val_mrcnn_mask_loss: 0.2009\n"
     ]
    }
   ],
   "source": [
    "# Fine tune all layers\n",
    "# Passing layers=\"all\" trains all layers. You can also \n",
    "# pass a regular expression to select which layers to\n",
    "# train by name pattern.\n",
    "model.train(dataset_train, dataset_val, \n",
    "            learning_rate=config.LEARNING_RATE / 10,\n",
    "            epochs=2, \n",
    "            layers=\"all\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Save weights\n",
    "# Typically not needed because callbacks save after every epoch\n",
    "# Uncomment to save manually\n",
    "model_path = os.path.join(MODEL_DIR, \"mask_rcnn_shapes_lvsolo.h5\")\n",
    "model.keras_model.save_weights(model_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Detection"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loading weights from  /home/lvshoulu/test-env3/src/github/Mask_RCNN/logs/shapes20180308T2211/mask_rcnn_shapes_0002.h5\n"
     ]
    }
   ],
   "source": [
    "class InferenceConfig(ShapesConfig):\n",
    "    GPU_COUNT = 1\n",
    "    IMAGES_PER_GPU = 1\n",
    "\n",
    "inference_config = InferenceConfig()\n",
    "\n",
    "# Recreate the model in inference mode\n",
    "model = modellib.MaskRCNN(mode=\"inference\", \n",
    "                          config=inference_config,\n",
    "                          model_dir=MODEL_DIR)\n",
    "\n",
    "# Get path to saved weights\n",
    "# Either set a specific path or find last trained weights\n",
    "# model_path = os.path.join(ROOT_DIR, \".h5 file name here\")\n",
    "model_path = model.find_last()[1]\n",
    "\n",
    "# Load trained weights (fill in path to trained weights here)\n",
    "assert model_path != \"\", \"Provide path to trained weights\"\n",
    "print(\"Loading weights from \", model_path)\n",
    "model.load_weights(model_path, by_name=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "original_image           shape: (128, 128, 3)         min:   27.00000  max:  218.00000\n",
      "image_meta               shape: (12,)                 min:    0.00000  max:  128.00000\n",
      "gt_class_id              shape: (3,)                  min:    1.00000  max:    3.00000\n",
      "gt_bbox                  shape: (3, 4)                min:    0.00000  max:  128.00000\n",
      "gt_mask                  shape: (128, 128, 3)         min:    0.00000  max:    1.00000\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x576 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Test on a random image\n",
    "image_id = random.choice(dataset_val.image_ids)\n",
    "original_image, image_meta, gt_class_id, gt_bbox, gt_mask =\\\n",
    "    modellib.load_image_gt(dataset_val, inference_config, \n",
    "                           image_id, use_mini_mask=False)\n",
    "\n",
    "log(\"original_image\", original_image)\n",
    "log(\"image_meta\", image_meta)\n",
    "log(\"gt_class_id\", gt_class_id)\n",
    "log(\"gt_bbox\", gt_bbox)\n",
    "log(\"gt_mask\", gt_mask)\n",
    "\n",
    "visualize.display_instances(original_image, gt_bbox, gt_mask, gt_class_id, \n",
    "                            dataset_train.class_names, figsize=(8, 8))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Processing 1 images\n",
      "image                    shape: (128, 128, 3)         min:   27.00000  max:  218.00000\n",
      "molded_images            shape: (1, 128, 128, 3)      min:  -76.90000  max:   94.30000\n",
      "image_metas              shape: (1, 12)               min:    0.00000  max:  128.00000\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x576 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "results = model.detect([original_image], verbose=1)\n",
    "\n",
    "r = results[0]\n",
    "visualize.display_instances(original_image, r['rois'], r['masks'], r['class_ids'], \n",
    "                            dataset_val.class_names, r['scores'], ax=get_ax())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Evaluation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mAP:  0.8000000029802322\n"
     ]
    }
   ],
   "source": [
    "# Compute VOC-Style mAP @ IoU=0.5\n",
    "# Running on 10 images. Increase for better accuracy.\n",
    "image_ids = np.random.choice(dataset_val.image_ids, 10)\n",
    "APs = []\n",
    "for image_id in image_ids:\n",
    "    # Load image and ground truth data\n",
    "    image, image_meta, gt_class_id, gt_bbox, gt_mask =\\\n",
    "        modellib.load_image_gt(dataset_val, inference_config,\n",
    "                               image_id, use_mini_mask=False)\n",
    "    molded_images = np.expand_dims(modellib.mold_image(image, inference_config), 0)\n",
    "    # Run object detection\n",
    "    results = model.detect([image], verbose=0)\n",
    "    r = results[0]\n",
    "    # Compute AP\n",
    "    AP, precisions, recalls, overlaps =\\\n",
    "        utils.compute_ap(gt_bbox, gt_class_id, gt_mask,\n",
    "                         r[\"rois\"], r[\"class_ids\"], r[\"scores\"], r['masks'])\n",
    "    APs.append(AP)\n",
    "    \n",
    "print(\"mAP: \", np.mean(APs))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.4.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
